package org.sraosha.microservice.gateway.filter;

import org.sraosha.framework.constants.RedisStorage;
import org.sraosha.framework.dto.ApiResult;
import org.sraosha.framework.enumeration.ApiResultEnum;
import org.sraosha.framework.manager.RedisManager;
import org.sraosha.microservice.gateway.value.FilterParamValue;
import com.alibaba.fastjson.JSON;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;

/**
 * 过滤器的抽象类
 */
public abstract class AbstractFilter {

    @Resource
    protected FilterParamValue filterParamValue;

    @Resource
    protected RedisManager redisManager;

//    @Resource
//    protected  PasswordEncoder passwordEncoder;

    /**
     * 判断当前路径是否需要过滤器处理
     *
     * @param targetUrl
     * @param exchange
     * @param chain
     * @return
     */
    protected Mono<Void> handle(String targetUrl, ServerWebExchange exchange, GatewayFilterChain chain) {
        if (exchange.getRequest().getPath().toString().contains(targetUrl)) {
            // 允许访问的路径，直接放行
            if (!this.checkAllowPathList(exchange, chain)) {

                ServerHttpResponse serverHttpResponse = exchange.getResponse();
                serverHttpResponse.getHeaders().setContentType(MediaType.APPLICATION_JSON);
                ApiResult<String> apiResult = new ApiResult<>();
                apiResult.setSuccess(Boolean.FALSE);

                // header中必须有token，并且在redis中存在
                if (!this.checkToken(exchange, chain)) {
                    apiResult.setCode(ApiResultEnum.TOKEN_ERROR.getCode());
                    apiResult.setMessage(ApiResultEnum.TOKEN_ERROR.getMessage());
                    String apiResultString = JSON.toJSONString(apiResult);
                    DataBuffer dataBuffer = serverHttpResponse.bufferFactory().allocateBuffer().write(apiResultString.getBytes(StandardCharsets.UTF_8));
                    return serverHttpResponse.writeWith(Mono.just(dataBuffer));
                }

                // header中必须有客户端身份识别的属性，并且在redis中存在
                if (!this.checkClient(exchange, chain)) {
                    apiResult.setCode(ApiResultEnum.AUTHORIZATION_ERROR.getCode());
                    apiResult.setMessage(ApiResultEnum.AUTHORIZATION_ERROR.getMessage());
                    String apiResultString = JSON.toJSONString(apiResult);
                    DataBuffer dataBuffer = serverHttpResponse.bufferFactory().allocateBuffer().write(apiResultString.getBytes(StandardCharsets.UTF_8));
                    return serverHttpResponse.writeWith(Mono.just(dataBuffer));
                }

                return chain.filter(exchange);
            } else {
                return chain.filter(exchange);
            }
        } else {
            return chain.filter(exchange);
        }
    }

    /**
     * 允许访问的路径，直接放行
     *
     * @param exchange
     * @param chain
     * @return
     */
    abstract Boolean checkAllowPathList(ServerWebExchange exchange, GatewayFilterChain chain);

    /**
     * header中必须有token，并且在redis中存在
     * @param exchange
     * @param chain
     * @return
     */
    abstract Boolean checkToken(ServerWebExchange exchange, GatewayFilterChain chain);

    /**
     * header中必须有客户端身份识别的属性，并且在redis中存在
     * @param exchange
     * @param chain
     * @return
     */
    abstract Boolean checkClient(ServerWebExchange exchange, GatewayFilterChain chain);
}
